package net.lee.shiro.demo.config.shiro;


import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.ExcessiveAttemptsException;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.stereotype.Component;

import java.util.concurrent.atomic.AtomicInteger;


/**
 * this is the CredentialsMatcher to Credentials the user password and the config user password
 * with the database or other config source
 * Create by lishijun on 2018/4/11
 * Company: lianzhong
 * Domain:  ourgame.com
 * Department:Web Developer
 */
@Component
public class RetryLimitHashedCredentialsMatcher extends HashedCredentialsMatcher {

    @Autowired
    private CacheManager cacheManager;


    public  RetryLimitHashedCredentialsMatcher()
    {
//        <property name="hashAlgorithmName" value="md5"/>
//        <property name="hashIterations" value="2"/>
//        <property name="storedCredentialsHexEncoded" value="true"/>
        this.setHashAlgorithmName("md5");
        //加密次数
        this.setHashIterations(2);
        this.setStoredCredentialsHexEncoded(true);
    }

    /**
     * 进行密码校验重试判断
     * @param token 用户登陆的token 保存信息
     * @param info 用户信息
     * @return 校验结果
     */
    @Override
    public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) {
        String username = (String)token.getPrincipal();
        //retry count + 1
        Cache passwordRetryCache = cacheManager.getCache("info_cache");
        AtomicInteger retryCount =new AtomicInteger(Integer.parseInt((passwordRetryCache.get(username)==null || passwordRetryCache.get(username).get()==null)?"0":passwordRetryCache.get(username).get().toString()));
        if(retryCount == null) {
            retryCount = new AtomicInteger(0);
            passwordRetryCache.put(username, retryCount);
        }
        if(retryCount.incrementAndGet() > 5) {
            //if retry count > 5 throw
            throw new ExcessiveAttemptsException();
        }
        // 执行最终的密码校验的过程
        boolean matches = super.doCredentialsMatch(token, info);
        if(matches) {
            //clear retry count
            passwordRetryCache.evict(username);
        }
        return matches;
    }

}
